import EntityStruct from "../Entity/EntityStruct";
import G from "../Utilities/Global";
import C from "../Configs/Config";
import EntityTypes from "../Constants/EntityTypes";
import Constants from "../Constants/Constants";
import MonsterAssetStruct from "../Structs/MonsterAssetStruct";

/**
 * 地图数据
 * created by Five on 2018-11-27 18:32:15
 */

export default class MapData {    // 宽高
    public Size: cc.Size = new cc.Size(1216, 704);
    // 所有物体的信息 位置
    public Entities: Array<EntityStruct> = new Array<EntityStruct>();
    // 隐藏的块,不能删,只能加
    public InvisEnt: Array<EntityStruct> = new Array<EntityStruct>();
    // 怪物
    public Monsters: Array<EntityStruct> = new Array<EntityStruct>();
    // 地图ID
    public MapID: number = 0;
    // 地图名字
    public MapName: string = "test";
    // 限定时间
    public TimeLimit: number = 9999;
    // 各自总数
    public GridCount: number = 0;
    // 地图背景
    public Background: string = "Scene background1";

    /**
     * 用一个不规则的自己来重构自己
     * @param ms 
     */
    constructor(ms?: MapData, isEdit?: boolean) {
        if (ms != null) {
            this.Size = ms.Size;
            this.MapID = ms.MapID;
            this.MapName = ms.MapName;
            this.Background = ms.Background ? ms.Background : this.Background;
            this.TimeLimit = ms.TimeLimit ? ms.TimeLimit : this.TimeLimit;
            this.GridCount = ms.Size.width * ms.Size.height / Math.pow(Constants.ENTITY_EDGE, 2);
            // 必须用创建的方式传递过去
            ms.Entities.forEach(e => {
                if (C().IsMonster(e.Asset) && !isEdit)
                    this.Monsters.push(new EntityStruct(e.Asset, e.Location))
                else {
                    if (C().IsTypeOf(e.Asset, EntityTypes.HIDE) && !isEdit) {
                        this.InvisEnt.push(new EntityStruct(e.Asset, e.Location));
                    } else {
                        this.Entities.push(new EntityStruct(e.Asset, e.Location));
                    }
                }
            });
        }
    }

    /**
     * 根据坐标查询地块 只关心会影响寻路的
     * @param position 位置
     */
    public GetWallByPosition(position: cc.Vec2): EntityStruct {
        let wall = this.GetWallByLocation(G().Calc.PositionToLocation(position), true);
        if (wall != null && C().IsTypeOf(wall.Asset, EntityTypes.AFFECTNAV))
            return wall;
        return null;
    }

    /**
     * 根据坐标查询是否有东西
     * @param position 位置
     * @param visOnly 只关心看得见的
     */
    public GetEntityByPosition(position: cc.Vec2, visOnly: boolean = false): EntityStruct {
        return this.GetWallByLocation(G().Calc.PositionToLocation(position), visOnly);
    }
    /**
     * 根据格子数查询地块
     * @param location 格子标记
     * @param visOnly 只关心看得见的
     */
    public GetWallByLocation(location: number, visOnly: boolean = false): EntityStruct {
        let es = this.Entities.find(e => e.Location == location);
        if (es == null && !visOnly)
            es = this.InvisEnt.find(e => e.Location == location);
        return es;
    }
    public GetEntityByType(type: number): EntityStruct {
        let es = this.Entities.find(e => (e.Asset.type & type) != 0);
        if (es == null)
            es = this.InvisEnt.find(e => (e.Asset.type & type) != 0);
        return es;
    }

    public GetEntitiesByType(type: number): Array<EntityStruct> {
        let result = new Array<EntityStruct>();
        for (let i = 0; i < this.Entities.length; i++) {
            if ((this.Entities[i].Asset.type & type) != 0)
                result.push(this.Entities[i])
        }
        for (let i = 0; i < this.InvisEnt.length; i++) {
            if ((this.InvisEnt[i].Asset.type & type) != 0)
                result.push(this.InvisEnt[i])
        }
        return result;
    }

    public PushEntity(es: EntityStruct) {
        let entity = this.GetWallByLocation(es.Location);
        if (entity) {
            this.RemoveEntity(entity);
            this.Entities.push(es);
        } else {
            this.Entities.push(es);
        }
    }

    public GetEntity(loc: number) {
        let es = this.Entities.find(x => x.Location == loc);
        if (es == null)
            es = this.InvisEnt.find(x => x.Location == loc);
        return es;
    }

    public RemoveEntity(es: EntityStruct | number): number {
        if (es == null)
            return 0;
        if (es instanceof EntityStruct) {
            let index = this.Entities.indexOf(es);
            if (index > -1) {
                this.Entities.splice(index, 1);
            }
            return es.Destory();
        } else {
            return this.RemoveEntity(this.GetEntity(es));
        }
    }
}